x86 Cx tracing: export the Cx exit reason (pending interrupt during Cx)
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 29 Jun 2009 10:01:50 +0000 (11:01 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 29 Jun 2009 10:01:50 +0000 (11:01 +0100)
Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
tools/xentrace/formats
xen/arch/x86/acpi/cpu_idle.c
xen/include/xen/trace.h

index db82a09250697a9d0c514ca0ceecfc94640318c0..976f3f89866db5e1173ab743d9ba916e558293f8 100644 (file)
 
 0x00801001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_freq_change [ %(1)dMHz -> %(2)dMHz ]
 0x00802001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_idle_entry  [ C0 -> C%(1)d, acpi_pm_tick = %(2)d, expected = %(3)dus, predicted = %(4)dus ]
-0x00802002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_idle_exit   [ C%(1)d -> C0, acpi_pm_tick = %(2)d ]
+0x00802002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_idle_exit   [ C%(1)d -> C0, acpi_pm_tick = %(2)d, irq = %(3)d %(4)d %(5)d %(6)d ]
index e98ef6a6933fe9838d1362963be56b58e3d57322..4d591c857e57f23e65bd9434679572589d30c73a 100644 (file)
@@ -190,6 +190,28 @@ static struct {
     unsigned int count;
 } c3_cpu_status = { .lock = SPIN_LOCK_UNLOCKED };
 
+static inline void trace_exit_reason(u32 *irq_traced)
+{
+#ifdef DEBUG
+    if ( unlikely(tb_init_done) )
+    {
+        int i, curbit;
+        u32 irr_status[8] = { 0 };
+
+        /* Get local apic IRR register */
+        for ( i = 0; i < 8; i++ )
+            irr_status[i] = apic_read(APIC_IRR + (i << 4));
+        i = 0;
+        curbit = find_first_bit((const unsigned long *)irr_status, 256);
+        while ( i < 4 && curbit < 256 )
+        {
+            irq_traced[i++] = curbit;
+            curbit = find_next_bit((const unsigned long *)irr_status, 256, curbit + 1);
+        }
+    }
+#endif
+}
+
 static void acpi_processor_idle(void)
 {
     struct acpi_processor_power *power = processor_powers[smp_processor_id()];
@@ -198,6 +220,7 @@ static void acpi_processor_idle(void)
     int sleep_ticks = 0;
     u32 t1, t2 = 0;
     u32 exp = 0, pred = 0;
+    u32 irq_traced[4] = { 0 };
 
     cpufreq_dbs_timer_suspend();
 
@@ -267,9 +290,10 @@ static void acpi_processor_idle(void)
             acpi_idle_do_entry(cx);
             /* Get end time (ticks) */
             t2 = inl(pmtmr_ioport);
+            trace_exit_reason(irq_traced);
             /* Trace cpu idle exit */
-            TRACE_2D(TRC_PM_IDLE_EXIT, cx->idx, t2);
-
+            TRACE_6D(TRC_PM_IDLE_EXIT, cx->idx, t2,
+                     irq_traced[0], irq_traced[1], irq_traced[2], irq_traced[3]);
             /* Re-enable interrupts */
             local_irq_enable();
             /* Compute time (ticks) that we were actually asleep */
@@ -326,8 +350,10 @@ static void acpi_processor_idle(void)
 
         /* recovering TSC */
         cstate_restore_tsc();
+        trace_exit_reason(irq_traced);
         /* Trace cpu idle exit */
-        TRACE_2D(TRC_PM_IDLE_EXIT, cx->idx, t2);
+        TRACE_6D(TRC_PM_IDLE_EXIT, cx->idx, t2,
+                 irq_traced[0], irq_traced[1], irq_traced[2], irq_traced[3]);
 
         if ( power->flags.bm_check && power->flags.bm_control )
         {
index 1ca52fc63311aa5269f8f98ff118a450a4ce90f6..797fb75658991bff50a136ad5538529d0b68f5d3 100644 (file)
@@ -111,4 +111,19 @@ static inline void trace_var(u32 event, int cycles, int extra,
         }                                                       \
     } while ( 0 )
 
+#define TRACE_6D(_e,d1,d2,d3,d4,d5,d6)                             \
+    do {                                                        \
+        if ( unlikely(tb_init_done) )                           \
+        {                                                       \
+            u32 _d[6];                                          \
+            _d[0] = d1;                                         \
+            _d[1] = d2;                                         \
+            _d[2] = d3;                                         \
+            _d[3] = d4;                                         \
+            _d[4] = d5;                                         \
+            _d[5] = d6;                                         \
+            __trace_var(_e, 1, sizeof(*_d)*6, (unsigned char *)_d); \
+        }                                                       \
+    } while ( 0 )
+
 #endif /* __XEN_TRACE_H__ */